// 引入登录/退出/获取用户的api接口函数
import { login, logout, getInfo } from '@/api/acl/user'
// 引入获取token/保存token/移除token的函数
import { getToken, setToken, removeToken } from '@/utils/auth'
// 引入重置路由的函数
import { resetRouter } from '@/router'
// 引入路由器对象
import router from '@/router'
// 引入常量路由/动态路由(异步路由)/任意路由
import { constantRoutes, asyncRoutes, anyRoutes } from '@/router/routes'
//引入深拷贝
import cloneDeep from 'lodash/cloneDeep'
// 初始化state对象的回调函数
const getDefaultState = () => {
  return {
    token: getToken(), // token
    name: '', // 用户名字
    avatar: '', // 头像

    buttons: [], // 按钮权限相关的数组
    roles: [], // 角色权限相关的数组
    asyncRoutes: [], // 异步路由数组
    routes: [] // 所有路由的相关数组


  }
}
// 创建一个state对象
const state = getDefaultState()
// mutations对象
const mutations = {
  // 重置state对象
  RESET_STATE: (state) => {
    Object.assign(state, getDefaultState())
  },
  // 保存token
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  // 保存用户名字
  SET_NAME: (state, name) => {
    state.name = name
  },
  // 保存头像信息
  SET_AVATAR: (state, avatar) => {
    state.avatar = avatar
  },


  // 保存用户信息
  SET_USER (state, { avatar, name, buttons, roles }) {
    state.avatar = avatar // 头像
    state.name = name // 用户名字
    state.buttons = buttons // 按钮数组
    state.roles = roles // 权限的数组

  },
  // 保存路由信息对象的
  SET_ROUTES (state, asyncRoutes) {
    // 一定是合并后的(已经过滤后的动态路由的数组)
    // 存储动态路由数组数据
    state.asyncRoutes = asyncRoutes
    // 合并路由数组
    state.routes = constantRoutes.concat(asyncRoutes, anyRoutes)
    // 再把异步路由和任意路由重新加入到常量路由中,真正的在路由器中合并路由数据
    router.addRoutes([...asyncRoutes, anyRoutes])
  }
}
// actions对象
const actions = {
  // 登录的action
  login ({ commit }, userInfo) {
    // 解构出帐号和密码
    const { username, password } = userInfo
    return new Promise((resolve, reject) => {
      // 调用login的api接口函数,并传入帐号和密码
      login({ username: username.trim(), password: password }).then(response => {
        // 登录成功后解构出所需要的data数据
        const { data } = response
        // 提交保存token的mutation
        commit('SET_TOKEN', data.token)
        // 使用cookies的方式存储token
        setToken(data.token)
        resolve()
      }).catch(error => {
        // 登录失败了
        reject(error)
      })
    })
  },

  // 获取用户信息的action
  getInfo ({ commit, state }) {
    return new Promise((resolve, reject) => {
      // 获取用户信息,不需要传入token
      getInfo().then(response => {
        // 解构出所需的data数据
        const { data } = response
        if (!data) {
          // 如果没有用户信息,则提示,重新的进行登录
          // 程序员开发的项目一定要懂得尊重用户
          return reject('请您重新登录')
        }
        // console.log(data)
        // 保存用户信息---保存到vuex中
        commit('SET_USER', data)
        // 过滤路由对象信息数据,并保存到vuex中
        //  asyncRoutes---动态路由数组, data.routes---路由名字数组
        //利用深拷贝克隆出asyncRoutes防止直接修改原数据
        //const resultRoutes = filterAsyncRoutes(asyncRoutes, data.routes)
        const resultRoutes = filterAsyncRoutes(cloneDeep(asyncRoutes), data.routes)
        commit('SET_ROUTES', resultRoutes)
        resolve(data)
        // console.log(data.routes)
        // console.log(asyncRoutes)
        // commit('SET_ROUTES',过滤后的动态路由数组)
        // commit('SET_ROUTES',data.routes---不是路由数组,是路由名字的数组,不要的)




        // 解构出用户的名字和头像
        // const { name, avatar } = data
        // // 保存用户名
        // commit('SET_NAME', name)
        // // 保存头像
        // commit('SET_AVATAR', avatar)
        // resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },

  // 退出的action
  logout ({ commit, state }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        removeToken() // 移除token
        resetRouter() // 重置路由
        commit('RESET_STATE') // 重置state
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // 移除token的action
  resetToken ({ commit }) {
    return new Promise(resolve => {
      removeToken() // 移除token
      commit('RESET_STATE') // 重置state
      resolve()
    })
  }
}

// 过滤路由对象信息数据的函数
function filterAsyncRoutes (routes, routeNames) {
  return routes.filter(route => {
    // 当前的路由对象的名字是否在路由名字数组中存在
    if (routeNames.includes(route.name)) {
      // 当前的路由对象中有没有子路由
      if (route.children && route.children.length > 0) {
        // 子路由中是否还有子路由对象
        const cRoute = filterAsyncRoutes(route.children, routeNames)
        // 判断子路由是否真的存在
        if (cRoute && cRoute.length > 0) {
          // 存储子路由
          route.children = cRoute
          return true
        }
        return false
      }
      return true
    }
    return false
  })
}
// 暴露出去user对象
export default {
  namespaced: true, // 开启命名空间
  state,
  mutations,
  actions
}